// JavaScript Document
function $F() {
    return document.getElementById(arguments[0]);
}

function $V() {
    return document.getElementById(arguments[0]).value;
}

function $C() {
    return document.createElement(arguments[0]);
}

Function.prototype.method = function(name, func) {
    //console.log( typeof this);
    this.prototype[name] = func;
    return this;
};

_dss_editor._toolkit = {
    /*
     * 由于clone的时候需要clone system以及system的连线，所以在clone的时候返回这2部分
     */
    clone : function(system) {
        var newLinks = [];
        var newSystem = this.cloneSystem(system, newLinks);
        for (var i = 0; i < newLinks.length; i++) {
            var newLink = newLinks[i];
            if (newLink.fromSystem == null || newLink.toSystem == null) {
                delete newLinks[i];
                if (newLink.fromSystem != null) {
                    newLink.fromSystem.removeLinkFrom(newLink);
                } else if (newLink.toSystem != null) {
                    newLink.toSystem.removeLinkTo(newLink);
                }
            }
        }
        var cloned = {
            system : newSystem,
            links : newLinks
        };
        return cloned;
    },
    cloneSystem : function(system, newLinks) {
        var newSystem = {};
        //复制基本信息
        newSystem.name = system.name || '';
        newSystem.type = system.type || '';
        newSystem.fullname = system.fullName || '';
        newSystem.basedOn = system.basedOn || '';
        newSystem.style = system.style || SYSTEM;
        newSystem.userDefinedType = system.userDefinedType || '';
        //由于连线是单独在下面复制，而且连线的复制不能复制from，to，name等 所以就不在这里进行复制
        newSystem.linkFrom = [];
        newSystem.linkTo = [];
        _dss_editor._model.system.initDiagram(newSystem);
        this.cloneShowInfo(newSystem, system);
        this.cloneProperty(newSystem, system);
        this.cloneSpecSys(newSystem, system);
        this.cloneContent(newSystem, system, newLinks);
        this.cloneSystemLinks(system, newSystem, newLinks);
        return newSystem;
    },
    /*
     * 复制系统的连线
     * 这里面会遇到 link.clone 这样一个临时增加的属性，用完之后需要删除掉。
     * 因为link有from和to，而每个system可能仅仅是from或者to
     * 如果每个system都将link from和link to进行复制，那么必然会产生重复的一条线出来
     * 所以这个属性意思是说这根线 我已经复制过了 只需要完善他的from或者to就行了。
     */
    cloneSystemLinks : function(system, newSystem, newLinks) {
        //复制 link from
        for (var i in system.getLinkFrom()) {
            var link = system.getLinkFrom()[i];
            var newLink = link.clone;
            if (!newLink) {
                newLink = this.cloneLink(link, newLinks);
                link.clone = newLink;
                newLinks.push(newLink);
            } else {                
                delete link.clone;
            }
            newLink.setFromSystem(newSystem);
            newSystem.addLinkFrom(newLink);
            _dss_editor._model.link.layout.apply(newLink);
        }
        for (var i in system.getLinkTo()) {
            var link = system.getLinkTo()[i];
            var newLink = link.clone;
            if (!newLink) {
                newLink = this.cloneLink(link, newLinks);
                link.clone = newLink;
                newLinks.push(newLink);
            } else {                
                delete link.clone;
            }
            newLink.setToSystem(newSystem);
            newSystem.addLinkTo(newLink);
            _dss_editor._model.link.layout.apply(newLink);
        }

    },
    /*
     * 复制显示的信息
     */
    cloneShowInfo : function(newSystem, system) {
        if (system.hasOwnProperty('showInfo')) {
            newSystem.showInfo = {};
            if (system.showInfo.hasOwnProperty('rectangle')) {
                newSystem.showInfo.rectangle = {};
                if (system.showInfo.rectangle.hasOwnProperty('x')) {
                    newSystem.showInfo.rectangle.x = system.showInfo.rectangle.x;
                }
                if (system.showInfo.rectangle.hasOwnProperty('y')) {
                    newSystem.showInfo.rectangle.y = system.showInfo.rectangle.y;
                }
                if (system.showInfo.rectangle.hasOwnProperty('w')) {
                    newSystem.showInfo.rectangle.w = system.showInfo.rectangle.w;
                }
                if (system.showInfo.rectangle.hasOwnProperty('h')) {
                    newSystem.showInfo.rectangle.h = system.showInfo.rectangle.h;
                }
            } else if (system.showInfo.hasOwnProperty('point')) {
                newSystem.showInfo.point = {};
                if (system.showInfo.point.hasOwnProperty('x')) {
                    newSystem.showInfo.point.x = system.showInfo.point.x;
                }
                if (system.showInfo.rectangle.hasOwnProperty('y')) {
                    newSystem.showInfo.point.y = system.showInfo.point.y;
                }
            }
            if (system.showInfo.hasOwnProperty('color')) {
                newSystem.showInfo.color = system.showInfo.color;
            }
            if (system.showInfo.hasOwnProperty('visible')) {
                newSystem.showInfo.visible = system.showInfo.visible;
            }
            if (system.showInfo.hasOwnProperty('showContent')) {
                newSystem.showInfo.showContent = system.showInfo.showContent;
            }
            if (system.showInfo.hasOwnProperty('showLabel')) {
                newSystem.showInfo.showLabel = system.showInfo.showLabel;
            }
        }
    },
    /*
     * 复制属性信息
     */
    cloneProperty : function(newSystem, system) {
        if (system.hasOwnProperty('property')) {
            newSystem.property = {};
            if (system.property.hasOwnProperty('hasShadow')) {
                newSystem.property.hasShadow = system.property.hasShadow;
            }
            if (system.property.hasOwnProperty('staticCnt')) {
                newSystem.property.staticCnt = system.property.staticCnt;
            }
            if (system.property.hasOwnProperty('version')) {
                newSystem.property.version = system.property.version;
            }
            if (system.property.hasOwnProperty('instantiate')) {
                newSystem.property.instantiate = system.property.instantiate;
            }
        }
    },
    /*
     * 复制user system信息
     */
    cloneBasedOn : function(newSystem, system) {
        if (system.hasOwnProperty('basedOn')) {
            newSystem.basedOn = {};
            if (system.basedOn.hasOwnProperty('base')) {
                newSystem.basedOn.base = system.basedOn.base;
            }
            if (system.basedOn.hasOwnProperty('isA')) {
                newSystem.basedOn.isA = system.basedOn.isA;
            }
        }
    },
    /*
     * 复制特定类型system类型特有的信息
     */
    cloneSpecSys : function(newSystem, system) {
        if (system.hasOwnProperty('specSys')) {
            newSystem.specSys = {};
            if (system.specSys.hasOwnProperty('work')) {
                newSystem.specSys.work = {};
                if (system.specSys.work.hasOwnProperty('deriveInfo')) {
                    newSystem.specSys.work.deriveInfo = {};
                    if (system.specSys.work.deriveInfo.hasOwnProperty('deriveFlag')) {
                        newSystem.specSys.work.deriveInfo.deriveFlag = system.specSys.work.deriveInfo.deriveFlag;
                    }
                    if (system.specSys.work.deriveInfo.hasOwnProperty('deriveProtoName')) {
                        newSystem.specSys.work.deriveInfo.deriveProtoName = system.specSys.work.deriveInfo.deriveProtoName;
                    }
                    if (system.specSys.work.deriveInfo.hasOwnProperty('partiProtoName')) {
                        newSystem.specSys.work.deriveInfo.partiProtoName = system.specSys.work.deriveInfo.partiProtoName;
                    }
                }
                if (system.specSys.hasOwnProperty('interactionFrom')) {
                    newSystem.interactionFrom = [];
                    for (var i in system.interactionFrom) {
                        newSystem.interactionFrom[i] = this.cloneInteraction(system.interactionFrom[i]);
                    }
                }
                if (system.specSys.hasOwnProperty('interactionTo')) {
                    newSystem.interactionTo = [];
                    for (var i in system.interactionTo) {
                        newSystem.interactionTo[i] = this.cloneInteraction(system.interactionTo[i]);
                    }
                }
            } else if (system.specSys.hasOwnProperty('protocol')) {
                newSystem.specSys.protocol = {};
                if (system.specSys.protocol.hasOwnProperty('simple')) {
                    newSystem.specSys.protocol.simple = {};
                    if (system.specSys.protocol.simple.hasOwnProperty('from')) {
                        newSystem.specSys.protocol.simple.from = system.specSys.protocol.simple.from;
                    }
                    if (system.specSys.protocol.simple.hasOwnProperty('to')) {
                        newSystem.specSys.protocol.simple.to = system.specSys.protocol.simple.to;
                    }
                }
            }
        }
    },
    /*
     * 复制内容
     */
    cloneContent : function(newSystem, system, newLinks) {
        if (system.hasOwnProperty('content')) {
            newSystem.content = {};
            if (system.content.hasOwnProperty('simple')) {
                newSystem.content.simple = {};
                if (system.content.simple.hasOwnProperty('expr')) {
                    newSystem.content.simple.expr = system.content.simple.expr;
                } else if (system.content.simple.hasOwnProperty('sysForView')) {
                    //newSystem.content.simple.expr = system.content.simple.expr;
                }
            } else if (system.content.hasOwnProperty('composite')) {
                newSystem.content.composite = {};
                if (system.content.composite.hasOwnProperty('subSys')) {
                    newSystem.content.composite.subSys = [];
                    for (var i in system.content.composite.subSys) {
                        newSystem.addChild(this.cloneSystem(system.content.composite.subSys[i], newLinks));
                    }
                }
                if (system.content.composite.hasOwnProperty('exitPoint')) {
                    newSystem.content.composite.exitPoint = [];
                    for (var i in system.content.composite.exitPoint) {
                        newSystem.addChild(this.clonePointAndCondition(system.content.composite.exitPoint[i], newLinks));
                    }
                }
                if (system.content.composite.hasOwnProperty('beginPoint')) {
                    newSystem.content.composite.beginPoint = [];
                    for (var i in system.content.composite.beginPoint) {
                        newSystem.addChild(this.clonePointAndCondition(system.content.composite.beginPoint[i], newLinks));
                    }
                }
                if (system.content.composite.hasOwnProperty('endPoint')) {
                    newSystem.content.composite.endPoint = [];
                    for (var i in system.content.composite.endPoint) {
                        newSystem.addChild(this.clonePointAndCondition(system.content.composite.endPoint[i], newLinks));
                    }
                }
                if (system.content.composite.hasOwnProperty('preCondition')) {
                    newSystem.content.composite.preCondition = [];
                    for (var i in system.content.composite.preCondition) {
                        newSystem.addChild(this.clonePointAndCondition(system.content.composite.preCondition[i], newLinks));
                    }
                }
                if (system.content.composite.hasOwnProperty('postCondition')) {
                    newSystem.content.composite.postCondition = [];
                    for (var i in system.content.composite.postCondition) {
                        newSystem.addChild(this.clonePointAndCondition(system.content.composite.postCondition[i], newLinks));
                    }
                }
                if (system.content.composite.hasOwnProperty('subArray')) {

                }
            }
        }
    },

    /*
     * 复制style为point
     */
    clonePointAndCondition : function(point, newLinks) {
        var newPoint = _dss_editor._model.system.createPoint(point.getType());
        newPoint.name = point.name;

        newPoint.showInfo.x = point.showInfo.x;
        newPoint.showInfo.y = point.showInfo.y;
        if (point.showInfo.hasOwnProperty('angle')) {
            newPoint.showInfo.angle = point.showInfo.angle;
        }
        this.cloneSystemLinks(point, newPoint, newLinks);
        return newPoint;
    },

    /*
     * 复制连线，连线中也有连接连线的情况，同样会使用link.clone这个临时变量
     */
    cloneLink : function(link, newLinks) {
        var newLink = _dss_editor._model.link.create(link.linkType);
        _dss_editor._model.link.initLink({
            diagrams : [],
            link : newLink
        });
        if (link.from) {
            newLink.from = link.from;
        }
        if (link.to) {
            newLink.to = link.to;
        }
        if (link.isDerived) {
            newLink.isDerived = link.isDerived;
        }
        if (link.content) {
            newLink.content = link.content;
        }
        if (link.linkFrom) {
            for (var i = 0; i < link.linkFrom.length; i++) {
                var l = link.linkFrom[i];
                var newL = l.clone;
                if (!newL) {
                    newL = this.cloneLink(l, newLinks);
                    l.clone = newL;
                    newLinks.push(newL);
                } else {                    
                    delete l.clone;
                }
                newL.setFromSystem(newLink);
                newLink.addLinkFrom(newL);
                _dss_editor._model.link.layout.apply(newL);
            }
        }
        if (link.showInfo) {
            newLink.showInfo = {};
            if (link.showInfo.hasOwnProperty('fromAngle')) {
                newLink.showInfo.fromAngle = link.showInfo.fromAngle;
            }
            if (link.showInfo.hasOwnProperty('toAngle')) {
                newLink.showInfo.toAngle = link.showInfo.toAngle;
            }
            if (link.showInfo.hasOwnProperty('visible')) {
                newLink.showInfo.visible = link.showInfo.visible;
            }
            if (link.showInfo.hasOwnProperty('color')) {
                newLink.showInfo.color = link.showInfo.color;
            }
        }
        return newLink;
    },

    /* 得到画布的context */
    getContext : function(canvasEntity) {
        // var canvas = $F("myCanvas");
        if (canvasEntity.getContext) {// 检测浏览器是否兼容
            ctx = canvasEntity.getContext("2d");
            // 你的canvas代码在这里
            ctx.strokeStyle = "black";
            // 线条的颜色
            ctx.fillStyle = "black";
            // 填充色
            ctx.lineWidth = 1;
            // 线条的宽度
            ctx.font = '10pt Arial';
            ctx.globalCompositeOperation = "default";
            return ctx;
        }
        return null;
    },
    /* 这里的名字是全路径名 */
    findSystemByName : function(diagrams, name) {
        var sys = null;
        if (name.indexOf('.') === 0) {//全路径
            name = name.substring(1, name.length);
        }
        for (var i = 0; i < diagrams.length; i++) {
            var diagram = diagrams[i];
            var firstName = name;
            var lastName = "";
            var index = 0;
            do {
                index = firstName.lastIndexOf('.');
                if (diagram.name == firstName) {
                    sys = diagram;
                    break;
                }
                lastName = name.substring(index + 1, name.length);
                firstName = firstName.substring(0, index);
            } while(index > 0);

            if (sys != null) {
                if (name != firstName) {
                    sys = this.findSystemByName(diagram.getChildren(), lastName);
                }
                break;
            }

        }
        return sys;
    },
    findLinkByName : function(links, name) {
        for (var i = 0; i < links.length; i++) {
            var link = links[i];
            if (link.name === name) {
                return link;
            }
        }
    },
    /*逻辑全路径名进行查找，主要是针对UIO*/
    findSystemByLogicName : function(diagrams, logicFullName) {
        for (var i = 0; i < diagrams.length; i++) {
            var diagram = diagrams[i];
            var fullName = diagram.getLogicFullName();
            if (fullName == logicFullName) {
                return diagram;
            } else {
                diagram = this.findSystemByLogicName(diagram.getChildren(), logicFullName);
                if (diagram != null) {
                    return diagram;
                }
            }
        }
        return null;
    },
    /*通过位置找到 system*/
    findSystemByLocation : function(diagrams, location, canvas) {
        var target = canvas.sys;
        try {
            for (var i = 0; i < diagrams.length; i++) {
                var diagram = diagrams[i];
                if (diagram.style == ARRAY) {
                    target = this.findSystemByLocation(diagram.subInstance, location, canvas);
                } else {
                    if (!diagram.isVisible()) {
                        continue;
                    }
                    var bounds = _dss_editor._toolkit.translateToAbsolute(diagram);
                    if (location.x > bounds.x && location.x < bounds.x + bounds.w && location.y > bounds.y && location.y < bounds.y + bounds.h) {
                        target = diagram;
                        if (diagram.hasOwnProperty("getChildren") && diagram.isShowContent()) {
                            var subDiag = this.findSystemByLocation(diagram.getChildren(), location, canvas);
                            if (subDiag != canvas.sys) {
                                target = subDiag;
                            }
                        }
                    }
                }
                if (target != canvas.sys) {
                    break;
                }
            }
        } catch (ex) {
            console.error(ex.stack);
        }
        return target;
    },
    findHandleByLocation : function(canvas, location) {
        var systems = canvas.selectionDiagrams;
        var links = canvas.selectionLinks;
        try {
            for (var i in systems) {
                var handles = systems[i].handles;
                for (var i = 0; i < handles.length; i++) {
                    var handle = handles[i];
                    var bounds = handle.bounds;
                    if (location.x > bounds.x && location.x < bounds.x + bounds.w && location.y > bounds.y && location.y < bounds.y + bounds.h) {
                        return handle;
                    }
                }
            }
            for (var i in links) {
                var handles = links[i].handles;
                for (var i = 0; i < handles.length; i++) {
                    var handle = handles[i];
                    var bounds = handle.bounds;
                    if (location.x > bounds.x && location.x < bounds.x + bounds.w && location.y > bounds.y && location.y < bounds.y + bounds.h) {
                        return handle;
                    }
                }
            }
        } catch (ex) {
            console.error(ex.stack);
        }
        return null;
    },

    findLinkByLocation : function(location, canvas) {
        var links = canvas.links;
        for (var i in links) {
            var link = links[i];
            if (link.getFromSystem() == null || link.getToSystem() == null || getValue(link.showInfo.visible) == NO) {
                continue;
            }
            var srcPoint = _dss_editor._model.link.getAnchorPoint(link.getFromSystem(), link.showInfo.fromAngle);
            var tarPoint = _dss_editor._model.link.getAnchorPoint(link.getToSystem(), link.showInfo.toAngle);
            var d1 = Math.ceil(Math.sqrt((srcPoint.x - location.x) * (srcPoint.x - location.x) + (srcPoint.y - location.y) * (srcPoint.y - location.y)));
            var d2 = Math.ceil(Math.sqrt((tarPoint.x - location.x) * (tarPoint.x - location.x) + (tarPoint.y - location.y) * (tarPoint.y - location.y)));
            var d3 = Math.ceil(Math.sqrt((srcPoint.x - tarPoint.x) * (srcPoint.x - tarPoint.x) + (srcPoint.y - tarPoint.y) * (srcPoint.y - tarPoint.y)));
            if (Math.abs(d1 + d2 - d3) <= 2) {
                return link;
            }
            var editArea = link.getEditArea();
            if (editArea.x <= location.x && editArea.x + editArea.w > location.x && editArea.y <= location.y && editArea.y + editArea.h > location.y) {
                return link;
            }
        }
        return null;
    },

    gotoSystem : function(system, canvas) {
        var current = canvas.getCurrentDrillSystem();
        var that = this;
        var scroll = function() {
            var rect = that.translateToAbsolute(system);
            var width = canvas.entity.parentNode.offsetWidth;
            var height = canvas.entity.parentNode.offsetHeight;
            var scrollLeft = canvas.entity.parentNode.scrollLeft;
            ;
            var scrollTop = canvas.entity.parentNode.scrollTop;
            if (rect.x + rect.w > width + scrollLeft || rect.x < scrollLeft) {
                canvas.entity.parentNode.scrollLeft = rect.x - 50;
            }
            if (rect.y + rect.h > height + scrollTop || rect.y < scrollTop) {
                canvas.entity.parentNode.scrollTop = rect.y - 50;
            }
        };
        if (!current) {
            current = canvas.sys;
        }
        if ($.inArray(system, _dss_editor._model.system.getAllSubs(current)) !== -1) {
            var hideSys = [];
            var superSys = system.parent;
            while (superSys.style != STYLE_ROOT) {
                if (!superSys.isShowContent()) {
                    hideSys.push(superSys);
                }
                superSys = superSys.parent;
            }
            while (hideSys.length > 0) {
                var needDrill = hideSys.pop();
                var cmd = new DrillCommand();
                cmd.canvas = canvas;
                cmd.system = needDrill;
                cmd.picked = cmd.DOWN;
                cmd.doCommand();
            }
            canvas.removeSelectionLink();
            canvas.removeSelectionSystem();
            canvas.addSelectionSystem(system);
            scroll();
            canvas.update();
        } else if (current.style != STYLE_ROOT) {
            canvas.drillUp();
            this.gotoSystem(system, canvas);
        }
    },
    // 相对坐标转换成绝对坐标
    translateToAbsolute : function(diagram) {
        var bounds = {};
        if (diagram.type == EXITPOINT || diagram.type == PRECOND || diagram.type == POSTCOND) {
            var superSys = diagram.parent;
            var loc = _dss_editor._model.link.getAnchorPoint(superSys, diagram.showInfo.angle);
            bounds = this.calculatePointBounds(loc, superSys, diagram.type);
        } else {
            var x = diagram.getRectangle().x;
            var y = diagram.getRectangle().y;
            var w = diagram.getRectangle().w;
            var h = diagram.getRectangle().h;

            while (!diagram.isDrilling && diagram.hasOwnProperty("parent") && diagram.parent.style != STYLE_ROOT) {// 如果有parent属性则进行累加
                if (ArrayTool.isArrayInstance(diagram)) {
                    diagram = diagram.parent;
                    continue;
                }
                x += diagram.parent.getRectangle().x;
                y += diagram.parent.getRectangle().y;
                if (diagram.parent.hasOwnProperty("isShowLabel") && diagram.parent.isShowLabel() == SHOW) {
                    y += labelHeight;
                }
                diagram = diagram.parent;
            }

            bounds.x = x;
            bounds.y = y;
            bounds.w = w;
            bounds.h = h;
        }
        return bounds;
    },
    // 绝对坐标转换成相对坐标
    translateToRelative : function(diagram, bounds) {
        var newBounds = {};
        var x = bounds.x;
        var y = bounds.y;
        if (diagram.type == EXITPOINT || diagram.type == POSTCOND || diagram.type == PRECOND) {
            var superSys = diagram.parent;
            var loc = _dss_editor._model.link.getAnchorPoint(superSys, diagram.showInfo.angle);
            newBounds = this.calculatePointBounds(loc, superSys, diagram.type);
        } else {
            // if (!diagram.isDrilling) {
            while (!diagram.isDrilling && diagram.hasOwnProperty("parent") && diagram.parent.style != STYLE_ROOT) {// 如果有parent属性则进行累加
                diagram = diagram.parent;
                if (diagram.style == ARRAY) {
                    continue;
                }
                x -= diagram.getRectangle().x;
                y -= diagram.getRectangle().y;
                if (diagram.isShowLabel() == SHOW) {
                    y -= labelHeight;
                }
            }
            // }
            newBounds.x = x;
            newBounds.y = y;
            newBounds.w = bounds.w;
            newBounds.h = bounds.h;
        }
        return newBounds;
    },
    //判断消息是否完整
    isMsgComplete : function(msg) {
        var head = msg.substring(0, 2);
        console.log(head);
        var length = 0;
        if (head == "##") {
            var i = msg.indexOf('{');
            var lenStr = msg.substring(2, i);
            length = parseInt(lenStr);
            _completeMsg = msg.substring(i, msg.length);
        }
        if (_completeMsg.length == length) {
            return true;
        }
        return false;
    },
    //转换成发送的消息
    stringifyToSendMessage : function(canvas) {
        var diagram = canvas.onDiagram;
        var links = canvas.sysForView.complete.links;
        if (canvas.type == _dss_editor._canvas._type.COMMAND) {
            //links = _dss_editor.canvas[_dss_editor.activeCanvas].sysForView.complete.links;
        }
        var msg = '{';
        msg += '"presenterName":"' + canvas.presenterName + '",';
        // msgType 需要用大括号括起来
        msg += '"msgType":{';
        // sysForView的结构
        msg += '"' + MSG_SEND + '":';

        // msg += '"complete":{';
        // sys的具体内容
        // msg += '"sys":[';
        msg += this.stringifySystemToJSON(diagram);
        // msg += ']}';
        // if (diagram.specSys && diagram.specSys.work && diagram.specSys.work.msgNameLabel) {
        // msg += this.stringifySysForViewToJSON(_dss_editor.canvas[diagram.specSys.work.msgNameLabel]);
        // }

        // ------结束
        msg += '}}';

        // JSON.parse(msg);
        msg = '##' + msg.length + msg;
        return msg;
    },

    stringifySysForViewToJSON : function(sysForView) {
        var msg = '"complete":{';
        //sys的具体内容
        msg += this.stringifySysToJSON(sysForView);
        msg += ',';
        //------结束
        msg += '"links":' + this.stringifyLinks(sysForView.complete.links);
        //link
        msg += '}';
        return msg;
    },

    stringifySysToJSON : function(sysForView) {
        var msg = '"sys":';
        // for (var i = 0; i < sysForView.complete.sys.length; i++) {
        // if (i != 0) {
        // msg += ',';
        // }
        // var diagram = sysForView.complete.sys[i];
        // msg += this.stringifySystemToJSON(diagram/*, canvas*/);
        // }
        msg += this.stringifySystemToJSON(sysForView.complete.sys);
        //msg += '}';
        return msg;
    },

    stringifySystemToJSON : function(diagram) {
        // name
        var msg = '{"name":"' + _dss_editor._toolkit.strReplaceAll(diagram.getName(), '"', '\\\"') + '"';
        if (diagram.hasOwnProperty('fullName')) {
            msg += ',"fullName":"' + _dss_editor._toolkit.strReplaceAll(diagram.fullName, '"', '\\\"') + '"';
        }
        if (diagram.hasOwnProperty('parent') && diagram.parent.hasOwnProperty('fullName')) {
            msg += ',"superSys":"' + _dss_editor._toolkit.strReplaceAll(diagram.parent.fullName, '"', '\\\"') + '"';
        }
        // type
        if (diagram.hasOwnProperty('type')) {
            msg += ',"type":\"' + diagram.type + '\"';
        }
        // type
        if (diagram.hasOwnProperty('userDefinedType')) {
            msg += ',"userDefinedType":\"' + diagram.userDefinedType + '\"';
        }
        // content 需要判断简单复合
        // if (diagram.hasOwnProperty('content')) {
        var content = this.stringifyContent(diagram/*, canvas*/);
        if (content != '') {
            msg += ',' + content;
        }

        // }
        // showInfo
        if (diagram.hasOwnProperty('showInfo')) {
            msg += ',' + this.stringifyShowInfo(diagram);
        }
        // property
        if (diagram.hasOwnProperty('property')) {
            msg += ',' + this.stringifyProperty(diagram);
        }
        // from link
        // if (diagram.hasOwnProperty('linkFrom')) {
        // msg += ',"linkFrom":' + this.stringifyLinks(diagram.linkFrom);
        // }
        // to link
        // if (diagram.hasOwnProperty('linkTo')) {
        // msg += ',"linkTo":' + this.stringifyLinks(diagram.linkTo);
        // }
        // specSys
        if (diagram.hasOwnProperty('specSys')) {
            msg += ',' + this.stringifySpecSys(diagram);
        }
        msg += '}';
        return msg;
    },

    stringifyArrayToJSON : function(array) {
        var msg = '{"name":"' + array.name + '"';
        msg += ',"subInstance":[';
        for (var i = 0; i < array.subInstance.length; i++) {
            if (i != 0) {
                msg += ',';
            }
            var sub = array.subInstance[i];
            msg += this.stringifySystemToJSON(sub, canvas);
        }
        msg += ']}';
        return msg;
    },

    stringifyContent : function(diagram) {
        var msg = '';
        if (diagram.specSys && diagram.specSys.work && diagram.specSys.work.msgNameLabel) {
            msg += '"content":{';
            var targetCanvas = _dss_editor.canvas[diagram.specSys.work.msgNameLabel];
            if (targetCanvas) {
                msg += '"' + SIMPLE + '":{"sysForView":{' + this.stringifySysForViewToJSON(targetCanvas.baseSysForView) + '}}}';
            }
        } else if (diagram.hasOwnProperty('content')) {
            msg += '"content":{';
            if (diagram.content.hasOwnProperty(SIMPLE) /*&& canvas.type != _dss_editor._canvas._type.COMMAND*/) {
                if (diagram.content.simple.hasOwnProperty('expr')) {
                    var expr = _dss_editor._toolkit.strReplaceAll(diagram.content.simple.expr, '"', '\\\"');
                    msg += '"' + SIMPLE + '":{"expr":"' + expr + '"}';
                }
            } else if (diagram.content.hasOwnProperty(COMPOSITE)) {
                var subSys = [];
                var beginPoint = [];
                var endPoint = [];
                var exitPoint = [];
                var subArray = [];
                if (false/*canvas.type == _dss_editor._canvas._type.COMMAND*/) {
                    //canvas = _dss_editor.canvas[_dss_editor.activeCanvas];
                    //subSys = canvas.sys;
                } else if (diagram.content.hasOwnProperty(COMPOSITE)) {
                    if (diagram.content.composite.hasOwnProperty('subSys')) {
                        subSys = diagram.content.composite.subSys;
                    }
                    if (diagram.content.composite.hasOwnProperty('subArray')) {
                        subArray = diagram.content.composite.subArray;
                    }
                    if (diagram.content.composite.hasOwnProperty('beginPoint')) {
                        beginPoint = diagram.content.composite.beginPoint;
                    }
                    if (diagram.content.composite.hasOwnProperty('endPoint')) {
                        endPoint = diagram.content.composite.endPoint;
                    }
                    if (diagram.content.composite.hasOwnProperty('exitPoint')) {
                        exitPoint = diagram.content.composite.exitPoint;
                    }
                }

                msg += '"' + COMPOSITE + '":{"subSys":[';
                for (var i = 0; i < subSys.length; i++) {
                    if (i != 0) {
                        msg += ',';
                    }
                    var sub = subSys[i];
                    msg += this.stringifySystemToJSON(sub, canvas);
                }
                msg += '],';
                msg += '"subArray":[';
                for (var i = 0; i < subArray.length; i++) {
                    if (i != 0) {
                        msg += ',';
                    }
                    var array = subArray[i];
                    msg += this.stringifyArrayToJSON(array, canvas);
                }
                msg += '],';
                msg += '"beginPoint":[';
                for (var i = 0; i < beginPoint.length; i++) {
                    if (i != 0) {
                        msg += ',';
                    }
                    var sub = beginPoint[i];
                    msg += this.stringifyPointToJSON(sub);
                }
                msg += '],';
                msg += '"endPoint":[';
                for (var i = 0; i < endPoint.length; i++) {
                    if (i != 0) {
                        msg += ',';
                    }
                    var sub = endPoint[i];
                    msg += this.stringifyPointToJSON(sub);
                }
                msg += '],';
                msg += '"exitPoint":[';
                for (var i = 0; i < exitPoint.length; i++) {
                    if (i != 0) {
                        msg += ',';
                    }
                    var sub = exitPoint[i];
                    msg += this.stringifyExitPointToJSON(sub);
                }
                msg += ']}';

            }
            msg += '}';
        }

        return msg;
    },

    stringifyPointToJSON : function(point) {
        var msg = '{"name":"' + point.getName() + '",';
        msg += '"showInfo":{';
        msg += '"x":' + point.showInfo.x + ',';
        msg += '"y":' + point.showInfo.y + '},';
        // from link
        msg += '"linkFrom":' + this.stringifyLinks(point.linkFrom) + ',';
        // to link
        msg += '"linkTo":' + this.stringifyLinks(point.linkTo);
        msg += '}';

        return msg;
    },

    stringifyExitPointToJSON : function(point) {
        var msg = '{"name":"' + point.getName() + '",';
        msg += '"showInfo":{';
        msg += '"angle":' + point.showInfo.angle + ',';
        msg += '"x":' + point.showInfo.x + ',';
        msg += '"y":' + point.showInfo.y + '},';
        // from link
        msg += '"linkFrom":' + this.stringifyLinks(point.linkFrom) + ',';
        // to link
        msg += '"linkTo":' + this.stringifyLinks(point.linkTo);
        msg += '}';
        return msg;
    },

    stringifyShowInfo : function(diagram) {
        var msg = '';
        if (diagram.hasOwnProperty('showInfo')) {
            var show = diagram.showInfo;
            msg += '"showInfo":{';
            if (show.hasOwnProperty('rectangle')) {
                msg += '"rectangle":{';
                msg += '"x":' + show.rectangle.x + ',';
                msg += '"y":' + show.rectangle.y + ',';
                msg += '"w":' + show.rectangle.w + ',';
                msg += '"h":' + show.rectangle.h + '}';
            }
            if (show.hasOwnProperty('showLabel')) {
                msg += ',"showLabel":"' + show.showLabel + '"';
            }
            if (show.hasOwnProperty('showContent')) {
                var showContent = show.showContent;
                if (diagram.hasOwnProperty('isDrilling')) {
                    showContent = NO;
                }
                msg += ',"showContent":"' + showContent + '"';
            }
            if (show.hasOwnProperty('color')) {
                msg += ',"color":"' + show.color + '"';
            }
            if (show.hasOwnProperty('visible')) {
                msg += ',"visible":"' + show.visible + '"';
            }
            msg += '}';
        }
        return msg;
    },

    stringifyProperty : function(diagram) {
        var msg = '';
        if (diagram.hasOwnProperty('property')) {
            var property = diagram.property;
            msg += '"property":{';
            //
            if (property.hasOwnProperty('hasShadow')) {
                msg += '"hasShadow":"' + property.hasShadow + '"';
            }
            if (property.hasOwnProperty('staticCnt')) {
                msg += ',"staticCnt":"' + property.staticCnt + '"';
            }
            if (property.hasOwnProperty('version')) {
                msg += ',"version":' + property.version;
            }
            if (property.hasOwnProperty('instantiate')) {
                msg += ',"instantiate":"' + property.instantiate + '"';
            }
            msg += '}';
        }
        return msg;
    },

    stringifySpecSys : function(diagram) {
        var msg = '';
        if (diagram.hasOwnProperty('specSys')) {
            var specSys = diagram.specSys;
            msg += '"specSys":{';
            if (specSys.hasOwnProperty('work')) {
                var needComma = false;
                msg += '"work":{';
                if (specSys.work.hasOwnProperty('deriveInfo')) {
                    var needComma1 = false;
                    msg += '"deriveInfo":{';
                    if (specSys.work.deriveInfo.hasOwnProperty('deriveFlag')) {
                        msg += '"deriveFlag":"' + specSys.work.deriveInfo.deriveFlag + '"';
                        needComma1 = true;
                    }
                    if (specSys.work.deriveInfo.hasOwnProperty('deriveProtoName')) {
                        if (needComma1) {
                            msg += ',';
                        }
                        msg += '"deriveProtoName":"' + specSys.work.deriveInfo.deriveProtoName + '"';
                        needComma1 = true;
                    }
                    if (specSys.work.deriveInfo.hasOwnProperty('partiProtoName')) {
                        if (needComma1) {
                            msg += ',';
                        }
                        msg += '"partiProtoName":"' + specSys.work.deriveInfo.partiProtoName + '"';
                    }
                    msg += '}';
                    needComma = true;
                }
                if (specSys.work.hasOwnProperty('interactionFrom')) {
                    if (needComma) {
                        msg += ',';
                    }
                    msg += '"interactionFrom":' + this.stringifyInteractions(specSys.work.interactionFrom);
                    needComma = true;
                }
                if (specSys.work.hasOwnProperty('interactionTo')) {
                    if (needComma) {
                        msg += ',';
                    }
                    msg += '"interactionTo":' + this.stringifyInteractions(specSys.work.interactionTo);
                    needComma = true;
                }
                if (specSys.work.hasOwnProperty('msgNameLabel')) {
                    if (needComma1) {
                        msg += ',';
                    }
                    msg += '"msgNameLabel":"' + specSys.work.msgNameLabel + '"';
                }
                msg += '}';
            } else if (specSys.hasOwnProperty('protocol')) {
                var needComma = false;
                msg += '"protocol":{';
                //	if (specSys.protocol.hasOwnProperty('simple')) {
                // msg += '"simple":{';
                if (specSys.protocol.hasOwnProperty('from')) {
                    msg += '"from":"' + specSys.protocol.from + '"';
                    needComma = true;
                }
                if (specSys.protocol.hasOwnProperty('to')) {
                    if (needComma) {
                        msg += ',';
                    }
                    msg += '"to":"' + specSys.protocol.to + '"';
                }
                //	}
                msg += '}';
            } else if (specSys.hasOwnProperty('nameLabel')) {
                msg += '"nameLabel":"' + specSys.nameLabel + '"';
            }
            msg += '}';
        }
        return msg;
    },

    stringifyLinks : function(links) {

        var msg = '[';
        for (var i in links) {
            var link = links[i];
            if (link.fromSystem == null || link.toSystem == null) {
                continue;
            }
            if (i > 0) {
                msg += ',';
            }
            msg += '{';
            if (link.name) {
                msg += '"name":"' + link.name + '"';
            } else {
                msg += '"name":"' + namePrefix + 'LINK_' + new Date().getTime() + '"';
            }
            if (link.hasOwnProperty('content')) {
                msg += ',"content":"' + link.content + '"';
            }
            if (link.hasOwnProperty('from')) {
                msg += ',"from":"' + link.from + '"';
            }
            if (link.hasOwnProperty('to')) {
                msg += ',"to":"' + link.to + '"';
            }
            if (link.hasOwnProperty('linkType')) {
                msg += ',"linkType":"' + link.linkType + '"';
            }
            if (link.hasOwnProperty('isDerived')) {
                msg += ',"isDerived":"' + link.isDerived + '"';
            }
            if (link.hasOwnProperty('showInfo')) {
                msg += ',"showInfo":{';
                if (link.showInfo.hasOwnProperty('fromAngle')) {
                    msg += '"fromAngle":' + link.showInfo.fromAngle;
                }
                if (link.showInfo.hasOwnProperty('toAngle')) {
                    msg += ',"toAngle":' + link.showInfo.toAngle;
                }
                if (link.showInfo.hasOwnProperty('visible')) {
                    msg += ',"visible":"' + link.showInfo.visible + '"';
                }
                if (link.showInfo.hasOwnProperty('color')) {
                    msg += ',"color":"' + link.showInfo.color + '"';
                }
                msg += '}';
            }
            msg += '}';
        }
        msg += ']';
        return msg;
    },

    trimStr : function(str) {
        // 去掉前面的空格
        while (str.charAt(0) == " ") {
            str = str.substring(1, str.length);
        }
        // 去掉 后面的空格
        while (str.charAt(str.length - 1) == " ") {
            str = str.substring(0, str.length - 2);
        }
        return str;
    },

    removeArrayElement : function(array, element) {
        for (var i = 0; i < array.length; i++) {
            if (array[i] == element) {
                array.splice(i, 1);
                break;
            };
        };
    },

    strReplaceAll : function(str, src, replace) {
        var ss = str.split(src);
        var t = '';
        for (var i in ss) {
            t = t.concat(ss[i]);
            if (i < ss.length - 1) {
                t = t.concat(replace);
            }
        }
        return t;
    },
    //适用于exitPoint precond postcond
    calculatePointBounds : function(loc, superSys, type) {
        var bounds = {};

        var dir = this.calculatePointDir(loc, superSys);
        if (dir == _dss_editor._model.system.DIR_EAST) {
            if (type == POSTCOND || type == PRECOND) {
                bounds.w = POINTLENGTH;
                bounds.h = POINTLENGTH;
            } else {
                bounds.w = EXITPOINTW;
                bounds.h = EXITPOINTH;
            }
            bounds.x = loc.x - bounds.w;
            bounds.y = loc.y - bounds.h / 2;
        } else if (dir == _dss_editor._model.system.DIR_WEST) {
            if (type == POSTCOND || type == PRECOND) {
                bounds.w = POINTLENGTH;
                bounds.h = POINTLENGTH;
            } else {
                bounds.w = EXITPOINTW;
                bounds.h = EXITPOINTH;
            }
            bounds.x = loc.x;
            bounds.y = loc.y - bounds.h / 2;
        } else if (dir == _dss_editor._model.system.DIR_NORTH) {

            if (type == POSTCOND || type == PRECOND) {
                bounds.w = POINTLENGTH;
                bounds.h = POINTLENGTH;
            } else {
                bounds.w = EXITPOINTH;
                bounds.h = EXITPOINTW;
            }
            bounds.x = loc.x - bounds.w / 2;
            bounds.y = loc.y;
        } else if (dir == _dss_editor._model.system.DIR_SOUTH) {

            if (type == POSTCOND || type == PRECOND) {
                bounds.w = POINTLENGTH;
                bounds.h = POINTLENGTH;
            } else {
                bounds.w = EXITPOINTH;
                bounds.h = EXITPOINTW;
            }
            bounds.x = loc.x - bounds.w / 2;
            bounds.y = loc.y - bounds.h;
        }

        if (type == POSTCOND || type == PRECOND) {
            bounds.w = POINTLENGTH;
            bounds.h = POINTLENGTH;
        }
        return bounds;
    },
    //适用于exitPoint precond postcond
    calculatePointDir : function(loc, superSys) {
        var pBounds = _dss_editor._toolkit.translateToAbsolute(superSys);
        var dir = _dss_editor._model.system.DIR_EAST;
        if (superSys.isShowLabel()) {
            pBounds.y += labelHeight;
            pBounds.h -= labelHeight;
        }
        if (loc.x == pBounds.x + pBounds.w) {
            dir = _dss_editor._model.system.DIR_EAST;
        } else if (loc.x == pBounds.x) {
            dir = _dss_editor._model.system.DIR_WEST;
        } else if (loc.y == pBounds.y) {
            dir = _dss_editor._model.system.DIR_NORTH;
        } else if (loc.y == pBounds.y + pBounds.h) {
            dir = _dss_editor._model.system.DIR_SOUTH;
        }
        return dir;
    },

    //以下三个方法是event中用，用于定位canvas中组件的位置
    getOffsetLocation : function(canvas) {
        var scollLoc = this.getScoll(canvas);
        var offsetLoc = this.getOffset(canvas);
        var location = {
            x : scollLoc.x - offsetLoc.x,
            y : scollLoc.y - offsetLoc.y
        };
        return location;
    },

    getOffset : function(canvas) {
        var parObj = canvas.entity.parentNode;
        var offsetLeft = canvas.entity.parentNode.offsetLeft;
        var offsetTop = canvas.entity.parentNode.offsetTop;
        while ( parObj = parObj.offsetParent) {
            offsetLeft += parObj.offsetLeft;
            offsetTop += parObj.offsetTop;
        }
        var location = {
            x : offsetLeft,
            y : offsetTop
        };
        return location;
    },

    getScoll : function(canvas) {
        var parObj = canvas.entity.parentNode;
        var scollTop = canvas.entity.parentNode.scrollTop;
        var scollLeft = canvas.entity.parentNode.scrollLeft;
        while ( parObj = parObj.offsetParent) {
            scollTop += parObj.scrollTop;
            scollLeft += parObj.scrollLeft;
        }
        var location = {
            x : scollLeft,
            y : scollTop
        };
        return location;
    },

    //此方法是用于定位工具的位置
    getToolOffsetLoc : function(canvas) {
        var parObj = canvas.entity.parentNode;
        var offsetX = parObj.offsetLeft;
        var offsetY = parObj.offsetTop;
        var scollTop = parObj.scrollTop;
        var scollLeft = parObj.scrollLeft;

        return {
            x : offsetX - scollLeft,
            y : offsetY - scollTop
        };
    },

    getSystemAllSubs : function(system) {
        var subs = [];
        //subs = subs.concat(system.getChildren());
        if (system.style != ARRAY) {
            for (var i in system.getChildren()) {
                var sub = system.getChildren()[i];
                subs.push(sub);
                var csubs = this.getSystemAllSubs(sub);
                subs = subs.concat(csubs);
            }
        }
        return subs;
    },

    getSystemAllInnerLinks : function(system) {
        var subs = this.getSystemAllSubs(system);
        subs.push(system);
        var links = [];
        for (var i = 0; i < subs.length; i++) {
            var sub = subs[i];
            if (sub.style == ARRAY) {
                for (var k in sub.subInstance) {
                    var ins = sub.subInstance[k];
                    links = links.concat(this.getSystemAllInnerLinks(ins));
                }
            } else {
                if (sub.getLinkFrom() != undefined) {
                    for (var j = 0; j < sub.getLinkFrom().length; j++) {
                        var link = sub.getLinkFrom()[j];
                        if ($.inArray(link.toSystem, subs) === -1) {
                            links.push(link);
                            continue;
                        }
                        if ($.inArray(link, links) === -1) {
                            links.push(link);
                        }
                    }
                }
                if (sub.getLinkTo() != undefined) {
                    for (var j = 0; j < sub.getLinkTo().length; j++) {
                        var link = sub.getLinkTo()[j];
                        if ($.inArray(link.fromSystem, subs) !== -1) {
                            continue;
                        }
                        if ($.inArray(link, links) === -1) {
                            links.push(link);
                        }
                    }
                }
            }
        }
        var linksLength = links.length;
        for (var i = 0; i < linksLength; i++) {
            var l = links[i];
            if (l.linkFrom) {
                this.getBranchLinks(l, links);
            }
        }
        return links;
    },

    getBranchLinks : function(link, links) {
        for (var i = 0; i < link.linkFrom.length; i++) {
            var l = link.linkFrom[i];
            if ($.inArray(l, links) === -1) {
                links.push(l);
            }
            if (l.linkFrom) {
                this.getBranchLinks(l, links);
            }
        }
    },

    isAroundParent : function(system) {
        if (system.getType() == EXITPOINT || system.getType() == PRECOND || system.getType() == POSTCOND) {
            return true;
        }
        return false;
    },

    measureText : function(str) {
        var canvas = _dss_editor.activeCanvas;
        canvas = _dss_editor.canvas[canvas];
        var w = 0;
        if (canvas != null) {
            w = _dss_editor._toolkit.getContext(canvas.entity).measureText(str).width + 50;
        }
        return w;
    }
};
//Array Tool
var ArrayTool = {
    isArrayInstance : function(instance) {
        var parent = instance.parent;
        if (parent.hasOwnProperty('style') && parent.style == ARRAY) {
            return true;
        }
        return false;
    },
    convertSys2Array : function(system, instanceNum) {
        instanceNum = parseInt(instanceNum);
        var array = null;
        if ( typeof (instanceNum) != 'number') {
            return;
        }
        if (this.isArrayInstance(system)) {

        } else {
            var parent = system.parent;
            parent.removeChild(system);
            var array = {
                name : system.name,
                subInstance : []
            };
            _dss_editor._model.system.initArray(array);
            array.addInstance(system);
            for (var i = 1; i < instanceNum; i++) {
                var instance = _dss_editor._toolkit.clone(system).system;
                instance.setVisible(NO);
                array.addInstance(instance);
                //instance.name = _dss_editor._toolkit.strReplaceAll(instance.name, '[*]', '[' + (i + 1) + ']');
            }
            //	system.name = _dss_editor._toolkit.strReplaceAll(system.name, '[*]', '[1]');
            parent.addChild(array);
        }
    },

    convertArray2Sys : function(array) {

    },

    gather : function(array, canvasId) {
        if (array.subInstance.length > 0) {
            for (var i = 1; i < array.subInstance.length; i++) {
                var instance = array.subInstance[i];
                instance.setVisible(NO);
            }
            array.subInstance[0].setStaticCnt(array.subInstance.length);
            array.subInstance[0].setHasShadow(YES);
        }
        matchCanvas(canvasId);
    },

    expand : function(array, canvasId) {
        for (var i = 0; i < array.subInstance.length; i++) {
            var instance = array.subInstance[i];
            instance.setVisible(YES);
            instance.setHasShadow(NO);
        }
        matchCanvas(canvasId);
    }
};
// UI Tool
// -----------------------------------------------------------------------------
var Layout = {
    //仅仅针对array编辑窗口进行布局是采用
    array_layout : function(array, canvas) {
        var x = 30, y = 30, space = 30;
        // var w = canvas.entity.
        for (var i in array.subInstance) {
            var ins = array.subInstance[i];
            if (!ins.isVisible()) {
                continue;
            }
            var rect = ins.getRectangle();
            rect.x = x;
            rect.y = y;
            ins.setRectangle(rect);
            _dss_editor._model.system.refreshSystemSelectionHandle(canvas);
            x += rect.w + space;
        }
    }
};

function HandleListener() {
    this.execute = function() {
    };
}

//handle 工具，主要用于编辑图形大小以及连线
function HandleTool(owner, canvasEntity, point) {
    this.owner = owner;
    this.bounds = {};
    this.canvasEntity = canvasEntity;
    this.listener = null;
    this.bounds.w = 15;
    this.bounds.h = this.bounds.w;
    this.bounds.x = point.x - this.bounds.w / 2;
    this.bounds.y = point.y - this.bounds.w / 2;

    this.handle = function() {
        if (this.listener != null) {
            this.listener.execute();
        }
    };
    this.draw = function() {
        var ctx = _dss_editor._toolkit.getContext(this.canvasEntity);
        var len = 5;
        var x = this.bounds.x + this.bounds.w / 2;
        var y = this.bounds.y + this.bounds.w / 2;
        ctx.strokeStyle = 'white';
        ctx.fillStyle = 'black';

        ctx.fillRect(x - len / 2, y - len / 2, len, len);
        ctx.strokeRect(x - len / 2, y - len / 2, len, len);
    };
    this.onSelect = function() {
    };
    this.addListener = function(listener) {
        this.listener = listener;
    };
}

function DscDialog(id, title, content, handler) {
    var that = this;
    that.id = id;
    that.title = title;
    that.content = content;
    that.handler = handler;
    that.show = function() {
        var parentNode = $F('canvas');
        var dialog = $C('div');
        dialog.id = this.id;
        parentNode.appendChild(dialog);
        $('#' + that.id).dialog({
            title : that.title,
            width : 300,
            height : 110,
            closed : false,
            cache : true,
            modal : true,
            resizeable : true,
            content : that.content,
            shadow : true,
            buttons : [{
                text : 'ok',
                handler : that.handler
            }, {
                text : 'cancel',
                handler : function() {
                    $('#' + that.id).dialog('destroy');
                }
            }]
        });
    };
}

function EditTool(canvas) {
    // <img onclick="drawText()" src="themes/icons/pencil.png" onmousemove="this.sytle.cursor = 'hand';"/>
    this.tool = $C('img');
    this.tool.canvas = canvas;
    this.parentNode = this.tool.canvas.entity.parentNode;
    this.imgPath = '';

    this.show = function() {
        this.layout();
        this.tool.setAttribute("src", this.imgPath/*"themes/icons/pencil.png"*/);
        this.parentNode.appendChild(this.tool);
    };

    this.close = function() {
        this.parentNode.removeChild(this.tool);
    };

    this.getLocation = function() {
    };

    this.setLocation = function(location) {
        this.getLocation = location;
    };

    this.setImgPath = function(imgPath) {
        this.imgPath = imgPath;
    };

    this.tool.handle = function() {

    };

    this.layout = function() {
        this.tool.setAttribute("style", "top:" + this.getLocation().y + "px;left:" + this.getLocation().x + "px;position:absolute;cursor:pointer");
    };

    this.setHandle = function(handle) {
        this.tool.handle = handle;
    };

    this.tool.onclick = function(e) {
        if (this.canvas.input) {
            this.canvas.input.commite();
        }
        this.handle();
    };

    this.tool.onmouseup = function(e) {
        this.canvas.mouseStatus = MOVE;
    };
}

function DscTextArea(canvas) {
    this.textarea = $C('textarea');
    this.panel = $C('div');
    this.canvas = canvas;
    this.parentNode = this.canvas.entity.parentNode;
    this.nicEditor = null;
    this.initText = '';

    this.textarea.id = 'textarea';
    this.panel.id = 'areapanel';
    this.panel.appendChild(this.textarea);

    this.show = function() {
        this.init();
        this.layout();
        this.parentNode.appendChild(this.panel);
        this.nicEditor = new nicEditor({
            buttonList : ['bold', 'italic']
        }).panelInstance('textarea');
        this.canvas.input = this;
    };

    this.commiteText = function() {
    };

    this.commite = function() {
        this.commiteText();
        this.close();
        this.canvas.update();
    };

    this.close = function() {
        this.parentNode.removeChild(this.panel);
    };

    this.getText = function() {
        if (this.nicEditor) {
            var t = this.nicEditor.nicInstances[0].getContent();
            return t;
        }
    };
    this.layout = function() {
        var top = this.getLocation().y - 20;
        var left = this.getLocation().x;
        this.panel.setAttribute("style", "top:" + top + "px;left:" + left + "px;position:absolute;font-size: 16px;background:white");
    };
    this.init = function() {
        // this.textarea.setAttribute("style", "background:#0000");
        this.textarea.setAttribute("cols", 30);
        this.textarea.setAttribute("rows", 10);
        this.textarea.innerHTML = this.initText;
    };
    this.getLocation = function() {
    };

    this.setLocation = function(location) {
        this.getLocation = location;
    };
}

function DscTextInput(canvas) {
	this.input = $C('input');
	this.panel = $C('div');
	this.canvas = canvas;
	this.parentNode = this.canvas.entity.parentNode;
	this.initText = '';
	this.panel.id = 'inputpanel';

	///@Robot 绘制选择列表etc.
	this.hintSelect = $C('select');
	this.hintSelect.size = DISPLAY_NUM;
	this.hintSelect.hidden = true;
	this.hintSelect.style.width = '100%';
	this.panel.appendChild(this.input);
	this.panel.appendChild(this.hintSelect);

	var that = this;
	var foundSys;
	var fullName;
	var cursorPosition = 0;
	var indexOfSplit = -1;
	var realString = '';
	var beforeSplitStr = '';
	var afterCursorPosition = '';
	var beforeCursorPosition = '';
	var lastCursorPosition = '';
	this.hintSelect.createOption = function(array, objToSetValue) {
		//array:source，option display，objToSetValue：object you wanto set value
		for (var i = 0; i < arguments[0].length; i++) {
			this.createOneOption(arguments[0][i], objToSetValue);
		}
	};
	this.hintSelect.createHintOption = function(array, objToSetValue, noValueHint) {
		//objToSetValue:if there no array,what you wanto display
		if ((arguments[0] || arguments[0].length == 0) && arguments[2]) {
			var option = $C('option');
			option.text = noValueHint;
			this.appendChild(option);
		} else {
			this.createOption(arguments[0], arguments[1]);
		}
	};
	this.hintSelect.createOneOption = function(textValue, objToSetValue) {
		var option = $C('option');
		option.text = arguments[0];
		option.ondblclick = function(e) {
			arguments[1] += e.currentTarget.value;
			this.hidden = true;
		};
		this.appendChild(option);
	};
	this.hintSelect.setHidden = function(bool) {
		this.hidden = bool;
	};
	this.input.isCharOrNumOrUnderline = function() {
		if (arguments[0] > 64 && arguments[0] < 91) {//A-Z
			return true;
		}
		if (arguments[0] > 95 && arguments[0] < 106) {//0-9
			return true;
		}
		if (arguments[0] > 47 && arguments[0] < 58) {//0-9
			return true;
		}
		if (arguments[0] == 189 && arguments[0].shiftKey == true) {// _
			return true;
		}
		return false;
	};
	this.input.strSplit = function(string, separatorArray) {
		//string:var string you wanto split,separator:separator
		var index = -1;
		for (var i = 0; i < separatorArray.length; i++) {
			if (index < string.lastIndexOf(separatorArray[i]))
				index = string.lastIndexOf(separatorArray[i]);
		}
		return index;
	};
	this.input.isHint = function(keyEvent) {
		if ((arguments[0].which == PERIOD && arguments[0].shiftKey == false) || arguments[0].which == NUM_PERIOD) {
			return true;
		}
		if (arguments[0].which == BACKSPACE) {
			return true;
		}
		if (that.input.isCharOrNumOrUnderline(arguments[0].keyCode)) {//
			return true;
		}
		return false;
	};
	this.input.getPostionForInput = function() {
		var currentPostion = 0;
		if (document.selection) {// IE Support
			this.focus();
			var Sel = document.selection.createRange();
			Sel.moveStart('character', -this.value.length);
			currentPostion = Sel.text.length;
		} else if (this.selectionStart || this.selectionStart == '0') {// Firefox support
			currentPostion = this.selectionStart;
		}
		return (currentPostion);
	};
	this.input.setCursorPosition = function(position) {
		if (this.setSelectionRange) {
			this.focus();
			this.setSelectionRange(position, position);
		} else if (this.createTextRange) {
			var range = this.createTextRange();
			range.collapse(true);
			range.moveEnd('character', position);
			range.moveStart('character', position);
			range.select();
		}
	};
	cursorPosition = this.input.getPostionForInput();

	this.input.filterStrFun = function(string, separator, autoComplete, indexOfSplit, cursorPosition) {
		//字符串过滤function，string：被分割的字符串，separator：分隔符，autoComplete：bool值是否自动补充
		var preName = '';
		var searchStr;
		var foundSystem;
		var preIndex = string.indexOf(separator);
		var suffixIndex = string.lastIndexOf(separator);
		var nameArray = [];
		if (that.hintSelect.length) {
			that.hintSelect.length = 0;
		}
		that.hintSelect.hidden = false;
		if (string.charAt(0) == '.') {//全路径开始的情况--'.'号开始
			if (preIndex == suffixIndex) {//一个点
				searchStr = string.substring(preIndex + 1, string.length);
				foundSystem = canvas.sysForView.complete.sys;
			} else if (suffixIndex > 0) {//两个点及以上
				preName = string.substring(0, suffixIndex);
				searchStr = string.substring(suffixIndex + 1, string.length);
				foundSystem = _dss_editor._toolkit.findSystemByName(canvas.sysForView.complete.sys.getChildren(), preName);
			}
			if (foundSystem) {//找到system则 进行匹配
				nameArray = _dss_editor._namespace.matchNames(searchStr, foundSystem, true);
			}
		} else if (string.charAt(0) != '.') {//相对路径 非'.'号开始
			if (preIndex < 0) {//0 '.'
				if (that.owner.parent) {
					nameArray = _dss_editor._namespace.matchNames(string, that.owner.parent, false);
				}

			} else if (preIndex > 0) {//1 or more than 1 '.'
				var preName = string.substring(0, suffixIndex);
				//preName = _preString.substring(_preString.lastIndexOf('.'), _preString.length);
				searchStr = string.substring(suffixIndex + 1, string.length);
				if (that.owner.parent) {
					foundSystem = _dss_editor._namespace.findSysInDomain(preName, that.owner.parent);
				}
				if (!foundSystem) {
					foundSystem = _dss_editor._namespace.findSysInExNS(preName, that.owner.parent);
				}
				nameArray = _dss_editor._namespace.matchNames(searchStr, foundSystem, true);
			}

		}
		if (nameArray.length == 0) {
			that.hintSelect.createHintOption([], that.input.value, "no suggestion");
		} else if (nameArray.length == 1 && autoComplete) {
			if (string.lastIndexOf('.') > 0) {
				that.input.value = beforeSplitStr + string.substring(0, string.lastIndexOf('.') + 1) + nameArray[0] + afterCursorPosition;
				that.input.setCursorPosition((beforeSplitStr + string.substring(0, string.lastIndexOf('.') + 1) + nameArray[0]).length);
			} else {
				that.input.value = beforeSplitStr + nameArray[0] + afterCursorPosition;
				that.input.setCursorPosition((beforeSplitStr + nameArray[0]).length);
			}
			that.hintSelect.hidden = true;
		} else if (nameArray.length > 0) {
			for (var i = 0; i < nameArray.length; i++) {
				var option = $C('option');
				option.text = nameArray[i];
				option.ondblclick = function(e) {
					if (string.lastIndexOf('.') > 0) {
						that.input.value = beforeSplitStr + string.substring(0, string.lastIndexOf('.') + 1) + e.currentTarget.value + afterCursorPosition;
						that.input.setCursorPosition((beforeSplitStr + string.substring(0, string.lastIndexOf('.') + 1) + e.currentTarget.value).length);
					} else {
						that.input.value = beforeSplitStr + e.currentTarget.value + afterCursorPosition;
						that.input.setCursorPosition((beforeSplitStr + e.currentTarget.value).length);
					}
					that.hintSelect.hidden = true;
				};
				that.hintSelect.appendChild(option);
			}

		}
	};
	this.hintSelect.onkeyup = function() {
		if (arguments[0].keyCode == ENTER) {
			var _selected = this.selectedIndex;
			if (realString.lastIndexOf('.') > 0) {
				that.input.value = beforeSplitStr + realString.substring(0, realString.lastIndexOf('.') + 1) + this[_selected].value + afterCursorPosition;
				that.input.setCursorPosition((beforeSplitStr + realString.substring(0, realString.lastIndexOf('.') + 1) + this[_selected].value).length);
			} else {
				that.input.value = beforeSplitStr + this[_selected].value + afterCursorPosition;
				that.input.setCursorPosition((beforeSplitStr + this[_selected].value).length);
			}
			this.hidden = true;
			that.input.focus();
		} else if (arguments[0].keyCode == ARROW_LEFT || arguments[0].keyCode == ARROW_RIGHT) {
			that.input.focus();
		}
	};
	///@Robot

	this.show = function() {
		this.init();
		this.layout();
		var len = this.initText.length + 5;
		if (len < 10) {
			len = 10;
		}
		this.input.setAttribute("size", len);
		this.parentNode.appendChild(this.panel);
		this.input.select();
		this.canvas.input = this;
	};

	this.commiteText = function() {
	};
	this.layout = function() {
		this.panel.setAttribute("style", "top:" + this.getLocation().y + "px;left:" + this.getLocation().x + "px;position:absolute;font-size: 16px;");
	};
	this.init = function() {
		this.input.setAttribute("type", "text");
		this.input.setAttribute("value", this.initText);
	};

	this.getLocation = function() {
	};

	this.setLocation = function(location) {
		this.getLocation = location;
	};

	this.commite = function() {
		this.commiteText();
		this.close();
		this.canvas.update();
	};

	this.close = function() {
		this.parentNode.removeChild(this.panel);
	};

	this.getText = function() {
		return this.input.value;
	};
	//@Robot 主要监视点号 backspace 向下方向键
	this.input.onkeyup = function(e) {
		lastCursorPosition = cursorPosition;
		console.log(lastCursorPosition + "  lastCursorPosition");
		if (arguments[0].keyCode != ARROW_DOWN) {
			cursorPosition = this.getPostionForInput();
			var strToSplit = this.value.substring(0, cursorPosition);
			indexOfSplit = this.strSplit(strToSplit, specialKeyArray) + 1;
			realString = that.input.value.substring(indexOfSplit, cursorPosition);
			beforeSplitStr = that.input.value.substring(0, indexOfSplit);
			afterCursorPosition = that.input.value.substring(cursorPosition);
			beforeCursorPosition = that.input.value.substring(0, cursorPosition);
		}
		console.log(cursorPosition + "  cursorPosition");

		if (arguments[0].keyCode == ARROW_DOWN) {//arrow down key
			if (that.hintSelect.length) {
				var _select = that.hintSelect;
				that.hintSelect.focus();
				that.hintSelect.selectedIndex = 0;
			}
		} else if (that.input.isHint(arguments[0])) {//'.' or num '.' ,backspace,num,Character key
			this.filterStrFun(realString, '.', 0, indexOfSplit, cursorPosition);
		} else if (arguments[0].keyCode == FORWARD_SLASH && arguments[0].altKey == true) {//alt+/ combo key
			this.filterStrFun(realString, '.', 1, indexOfSplit, cursorPosition);
		}
	};
}

function DscComboTextInput(canvas) {
    this.input = $C('input');
    this.panel = $C('div');
    this.canvas = canvas;
    this.parentNode = this.canvas.entity.parentNode;
    this.initText = '';
    this.dataList = [];

    this.panel.id = 'inputpanel';
    this.input.id = 'combo';
    this.panel.appendChild(this.input);

    this.show = function() {
        //this.init();
        this.layout();
        this.parentNode.appendChild(this.panel);
        $('#combo').combobox({
            valueField : 'id',
            textField : 'text',
            panelHeight : 100,
            height : 20,
            width : 100,
            value : this.initText,
            hasDownArrow : true,
            data : this.dataList,
            onChange : function() {

            }
        });
        this.canvas.input = this;
        var entity = $('#combo').combobox('textbox');
        entity.select();
    };

    this.commiteText = function() {
    };
    this.layout = function() {
        this.panel.setAttribute("style", "top:" + this.getLocation().y + "px;left:" + this.getLocation().x + "px;position:absolute;font-size: 16px;");
    };
    this.init = function() {
        this.input.setAttribute("type", "text");
        this.input.setAttribute("value", this.initText);
    };

    this.getLocation = function() {
    };

    this.setLocation = function(location) {
        this.getLocation = location;
    };

    this.commite = function() {
        this.commiteText();
        this.close();
        this.canvas.update();
    };

    this.close = function() {
        this.parentNode.removeChild(this.panel);
    };

    this.getText = function() {
        return this.text = $('#combo').combobox("getText");
    };

}

